/**
 * Copyright (C) 2013-2014 the original author or authors.
 */
package com.foreveross.bsl.mongodb.repository.source;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.data.mongodb.MongoDbFactory;

import com.foreveross.bsl.mongodb.repository.MongodbConfig;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoOptions;
import com.mongodb.ServerAddress;

/**
 * @description
 *
 * @author rening
 * @version v1.0
 *
 * @2013-7-18
 *
 */
public class MongodbSources {

	private static Map<String, Mongo> mongoMap = new HashMap<String, Mongo>();

	private static String databaseInfo = "database_info"; //database setting
	
	public static Mongo getMongo(String connName){
		return mongoMap.get(connName);
	}
	
	public static void init(MongodbConfig config, MongoDbFactory factory) {
		DB db = factory.getDb(); // 初始化时提供库路由功能
		MongoOptions options = config.getOptions();
		DBCollection coll;
		if(!db.collectionExists(databaseInfo)) {
			BasicDBObject ob = new BasicDBObject();
			ob.put("capped", false);
			coll = db.createCollection(databaseInfo, ob);
		}
		coll = db.getCollection(databaseInfo);
		DBCursor cursor = coll.find();
		try {
			StringBuffer addrString = new StringBuffer();
			List<ServerAddress> addrs = db.getMongo().getServerAddressList();
			if(addrs !=null && !addrs.isEmpty()){
				for (ServerAddress serverAddress : addrs) {
					addrString.append(serverAddress.getHost());
					if(serverAddress.getPort() > 0) {
						addrString.append(":").append(serverAddress.getPort());
					}
					addrString.append(",");
				}
				addrString.deleteCharAt(addrString.lastIndexOf(","));
			}
			if(cursor == null || cursor.count() < 1){
				coll.insert(new BasicDBObject("connName", "default").append("serverAddress", addrString.toString()));
				mongoMap.put("default", db.getMongo());
			} else {
				DBObject obj;
				String connName;
				String serverAddress;
				Mongo mongo = null;
				while(cursor.hasNext()) {
					obj = cursor.next();
					connName = (String)obj.get("connName");
					serverAddress = (String)obj.get("serverAddress");
					if(addrString.toString().equals(serverAddress)){
						mongo =db.getMongo();
					} else {
						mongo = createMongo(serverAddress, options); // 启动时，自动创建mongodb
					}
					mongoMap.put(connName, mongo);
			   }
			}
		} finally {
			if(cursor != null){
				cursor.close();
			}
		}
	}

	/**
	 * @param obj
	 * @param mongo
	 * @return
	 */
	private static Mongo createMongo(String serverAddress, MongoOptions options) {
		Mongo mongo = null;
		if(serverAddress != null){
			List<ServerAddress> addrList = new ArrayList<ServerAddress>();
			if(serverAddress.indexOf(",") != -1 ){
				String[] addrs=serverAddress.split(",");
				for (int i = 0; i < addrs.length; i++) {
					try {
						if(addrs[i].indexOf(":") != -1){
							String[] ipFmat = addrs[i].split(":");
							addrList.add(new ServerAddress(ipFmat[0], Integer.parseInt(ipFmat[1])));
						}else{
							addrList.add(new ServerAddress(addrs[i]));
						}
					} catch (NumberFormatException e) {
						throw new RuntimeException("init mongodb connection error", e);
					} catch (UnknownHostException e) {
						throw new RuntimeException("init mongodb connection error", e);
					}
				}
				mongo = new Mongo(addrList, options);
			} else {
				try {
					mongo = new Mongo(serverAddress, options);
				} catch (UnknownHostException e) {
					throw new RuntimeException("init mongodb connection error",e);
				}
			}
		}
		return mongo;
	}
}
